package com.qf.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * RabbitMQ ： 生产者 发消息给 交换机  交换机没有收到或收到 进行应答  （确认模式）
 * RabbitMQ ： 交换机 路由消息给队列   队列没有收到 找生产者进行应答  （确认模式）
 *
 *   1、交换机或队列 默认情况下：不进行应答  （确认模式默认是不开启的）   开启浪费资源
 *       publisher-confirms: true   #开启交换机应答  confirms
 *       publisher-returns: true    # 开启队列应答   returns
 *   2、交换机或队列 应答生产者  生产者是怎么接收到的应答的消息呢？
 *      	private ConfirmCallback confirmCallback;   接收交换机应答消息的
 * 	        private ReturnCallback returnCallback;   接收队列的应答消息
 *
 * @author lixu
 *
 * <bean id="" class=com.qf.config.RabbitConfirmConfig init=
 *
 * @Configuration  spring-context.xml
 */
@Configuration
@Slf4j
public class RabbitConfirmConfig implements InitializingBean, BeanPostProcessor,  RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 后处理器  之  初始化之前
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    //构造器
    /**'
     *   SpringIOC容器创建对象的时候 生命周期
     *     创建对象 --》 构造器 --》依赖注入  --》初始化之前  --> 自定义初始化 --》 初始化 --》初始化之后 --》 销毁  单例
     *
     *
     *     创建对象 --》构造器 --》 依赖注入 -->初始化 --》 JVM垃圾回收  多例
     *
     */
    @PostConstruct //自定义初始化
    public void abc() {
        rabbitTemplate.setConfirmCallback(this);//this: 当前对象的引用  地址   空指针异常
        rabbitTemplate.setReturnCallback(this);
    }
       //初始化
    @Override
    public void afterPropertiesSet() throws Exception {
        //
    }

    /**
     * 后处理器  之  初始化之后
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }




    /**
     * 问题：
     *   实现类 implements 内部接口
     *
     *    方法实现了
     *
     */
    /**
     * 交换机要应答的时候 ： 调用上面的这个接口
     */






    /**
     * 交换机应答实现方法
     *    成功或失败都要进行应答
     * @param correlationData
     * @param ack  ： true: 接收消息成功  false:消息丢失
     * @param cause : 原因 ： 成功   失败：有原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            log.info("交换机接收消息成功:{}",cause);//cause:null
        }else{
            log.error("交换机接收消息失败:{}",cause);
        }
    }

    /**
     * 队列应答实现方法
     *    只有失败了才应答
     * @param message
     * @param replyCode
     * @param replyText
     * @param exchange
     * @param routingKey
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {

        log.error("队列接收消息失败:{}",replyCode);//403
        log.error("队列接收消息失败:{}",replyText);//文字显示

        //重新发送消息  给2-3次 转人工

    }


}
